package com.lucanjun.cn.springsecurity.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.YearMonth;
import java.util.*;

/**
 * @author lucanjun
 * @create 2025-03-10
 * @describe 日期工具类
 */
@Slf4j
public class DateUtil {
    public static final String FORMAT_NO_LINE = "yyyyMMddHHmmssSSS";
    public static final String FORMAT_LINE = "yyyy-MM-dd HH:mm:ss:SSS";
    public static final String FORMAT_SECOND = "yyyy-MM-dd HH:mm:ss";
    public static final String FORMAT_DAY = "yyyy-MM-dd";
    public static final String FORMAT_DAY1 = "yyyy/MM/dd";
    public static final String FORMAT_DAY_CHINAESE = "yyyy年MM月dd日";
    public static final String FORMAT_DAY_POINT = "yyyy.MM.dd";
    public static final String FORMAT_POINT_SECOND = "yyyy.MM.dd HH:mm:ss";
    public static final String FORMAT_CHINAESE_SECOND = "yyyy年MM月dd日 HH时mm分ss秒";
    public static final String FORMAT_MONTH_LINE = "yyyy-MM";

    private DateUtil() {

    }

    /**
     * 获取指定时间-格式的字符串日期
     *
     * @param date
     * @param format
     * @return
     */
    public static String formatDateString(Date date, String format) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        String dateString = simpleDateFormat.format(date);
        return dateString;
    }

    /**
     * 获取指定字符串时间-格式的时间日期
     *
     * @param dateString
     * @param format
     * @return
     */
    public static Date formatDate(String dateString, String format) {
        if (StringUtils.isBlank(dateString)) {
            return null;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        Date date = null;
        try {
            date = simpleDateFormat.parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    public static String toTime(Date date) {
        return formatDateString(date, FORMAT_SECOND);
    }

    public static Date toTime(String dateStr) {
        return formatDate(dateStr, FORMAT_SECOND);
    }

    public static Date toDay(String dateStr) {
        return formatDate(dateStr, FORMAT_DAY);
    }

    public static String toDay(Date date) {
        return formatDateString(date, FORMAT_DAY);
    }

    /**
     * 获取当前日期前一天
     *
     * @return
     */
    public static Date getYesterdayTime() {
        Calendar ca = Calendar.getInstance();//得到一个Calendar的实例
        ca.setTime(new Date()); //设置时间为当前时间
        ca.add(Calendar.DATE, -1);
        Date lastDay = ca.getTime(); //结果
        return lastDay;
    }

    /**
     * 获取两个日期之间相差天数
     *
     * @param date1
     * @param date2
     * @return
     */
    public static Long getDiffDays(Date date1, Date date2) {
        Long diff = date2.getTime() - date1.getTime();
        Long days = diff / (24 * 60 * 60 * 1000);
        return days;
    }

    /**
     * 增加或减少指定日期的天数
     *
     * @param date
     * @param day
     * @return
     */
    public static Date addDays(Date date, Integer day) {
        if (date == null) date = new Date();
        if (day == null) day = 1;

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, day);//+1今天的时间加一天
        date = calendar.getTime();
        return date;
    }

    /**
     * 增加或减少指定日期的月份
     *
     * @param date
     * @param day
     * @return
     */
    public static Date addMonths(Date date, Integer month) {
        if (date == null) date = new Date();
        if (month == null) month = 1;

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, month);//+1今天的时间加一天
        date = calendar.getTime();
        return date;
    }

    /**
     * 获取指定日期的 00:00:00
     *
     * @param date
     * @return
     */
    public static Date getDateTimeFirstToDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date time = calendar.getTime();
        return time;
    }

    /**
     * 获取指定日期的 23:59:59
     *
     * @return
     */
    public static Date getDateTimeLastToDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 0);
        Date time = calendar.getTime();
        return time;
    }

    /**
     * 获取指定日期的月份数
     *
     * @param date
     * @return
     */
    public static int getMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH) + 1;
    }

    /**
     * 获取指定日期的年份数
     *
     * @param date
     * @return
     */
    public static int getYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.YEAR);
    }

    /**
     * 获取指定月份的第一天0秒
     *
     * @param month
     * @return
     */
    public static Date getMonthOfFirstDay(int month) {
        Calendar calendar = Calendar.getInstance();
        // 设置月份
        if (month != 0) {
            calendar.set(Calendar.MONTH, month - 1);
        }
        // 获取某月最小天数
        int firstDay = calendar.getActualMinimum(Calendar.DAY_OF_MONTH);
        // 设置日历中月份的最小天数
        calendar.set(Calendar.DAY_OF_MONTH, firstDay);
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_DAY);
        String first = sdf.format(calendar.getTime()) + " 00:00:00";
        Date toTime = toTime(first);
        return toTime;
    }

    /**
     * 获取指定月份的最后一天最后一秒
     *
     * @param month
     * @return
     */
    public static Date getMonthOfLastDay(Date date, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int year = getYear(date);
        // 设置月份
        if (month != 0) {
            calendar.set(Calendar.MONTH, month - 1);
        }
        // 获取某月最大天数
        int lastDay = 0;
        //2月的平年瑞年天数
        if (month == 2) {
            YearMonth yearMonth = YearMonth.of(year, 2);
            lastDay = yearMonth.lengthOfMonth();
        } else {
            lastDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        }
        // 设置日历中月份的最大天数
        calendar.set(Calendar.DAY_OF_MONTH, lastDay);
        // 格式化日期
        SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_DAY);
        String last = sdf.format(calendar.getTime()) + " 23:59:59";
        Date toTime = toTime(last);
        return toTime;
    }

    /**
     * 指定日期转时间戳
     *
     * @param date
     * @return
     */
    public static Long dateToStamp(Date date) {
        return date.getTime();
    }

    public static Date dateToStampToDate(Long dateToStamp) {
        Date date = new Date(dateToStamp);
        SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_SECOND);
        String dateString = sdf.format(date);
        Date toTime = toTime(dateString);
        return toTime;
    }

    /**
     * 获取指定日期当天距离指定日期当天结束23:23:59还有多少秒
     *
     * @param date
     * @return
     */
    public static long getSecondByEndToday(Date date) {
        long time = date.getTime();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return ((calendar.getTimeInMillis() - time) / 1000);
    }

    /**
     * 获取指定日期当天距离指定日期当月结束23:23:59还有多少秒
     *
     * @param date
     * @return
     */
    public static long getSecondByMonthEndDay(Date date) {
        long time = date.getTime();
        int month = getMonth(date);
        Date monthOfLastDay = getMonthOfLastDay(date, month);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(monthOfLastDay);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return ((calendar.getTimeInMillis() - time) / 1000);
    }

    /**
     * date1.after(date2)
     * 当date1大于date2时，返回TRUE，
     * 当date1小于等于date2时，返回false；
     *
     * @param date1
     * @param date2
     * @return
     */
    public static boolean after(Date date1, Date date2) {
        boolean after = date1.after(date2);
        if (after) {
            log.info("时间对比的结果为：true，date1大于date2");
        }
        if (!after) {
            log.info("时间对比的结果为：false，date1小于等于date2");
        }
        return after;
    }

    /**
     * date1.before(date2)
     * 当date1小于date2时，返回TRUE，
     * 当date1大于等于date2时，返回false；
     *
     * @param date1
     * @param date2
     * @return
     */
    public static boolean before(Date date1, Date date2) {
        boolean before = date1.before(date2);
        if (before) {
            log.info("时间对比的结果为：true，date1小于date2");
        }
        if (!before) {
            log.info("时间对比的结果为：false，date1大于等于date2");
        }
        return before;
    }

    /**
     * date1.compareTo(date2)
     * 当date1 == date2，返回值为0
     * 当date1 > date2，返回值大于0
     * 当date1 < date2，返回值小于0
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int compareTo(Date date1, Date date2) {
        int compareTo = date1.compareTo(date2);
        if (compareTo == 0) {
            log.info("时间对比的结果为：0，date1等于date2");
        }
        if (compareTo > 0) {
            log.info("时间对比的结果为：大于0，date1大于date2");
        }
        if (compareTo < 0) {
            log.info("时间对比的结果为：小于0，date1小于date2");
        }
        return compareTo;
    }

    public static String formatToFormatDateString(String startDate, String format, String toFormat) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        SimpleDateFormat dateFormat2 = new SimpleDateFormat(toFormat);
        Date date = null;
        try {
            date = dateFormat.parse(startDate);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        String dateString = dateFormat2.format(date);
        return dateString;
    }

    public static void main(String[] args) {
        String toTime = toDay(new Date());
        System.out.println(toTime);
        System.out.println(formatToFormatDateString(toTime, DateUtil.FORMAT_DAY, DateUtil.FORMAT_DAY1));
    }

}